<?php

namespace app\admin\command;

use app\admin\command\Api\library\Builder;
use phpspider\core\phpspider;
use think\Config;
use think\console\Command;
use think\console\Input;
use think\console\input\Option;
use think\console\Output;
use think\Db;
use think\Exception;

class Test extends Command
{
    protected function configure()
    {
        /* Do NOT delete this comment */
        /* 不要删除这段注释 */
        $this->setName('test')->setDescription('Here is the remark ');
    }

    protected function execute(Input $input, Output $output)
    {
        /* Do NOT delete this comment */
        /* 不要删除这段注释 */
        $dir = dirname(__FILE__);
        $configs = array(
            'name' => '保温网',
            'log_show' => false,
            'log_file' => $dir.'/log/test_baowenwang.log',
            'log_type' => 'error,warn,debug',
            'input_encoding' => null,  //input_encoding默认值为null，即程序自动识别页面编码
            'output_encoding' => 'utf-8', //output_encoding默认值为utf-8, 如果数据库为gbk编码，请修改为gb2312
            'tasknum' => 1,      //tasknum默认值为1，即单进程任务爬取     进程数
            'timeout' => 5,     //爬虫爬取每个网页的超时时间 单位秒
            'max_try' => 2 ,    // 爬虫爬取每个网页失败后尝试次数 重复爬取2次
            'max_depth' => 3,   //爬虫爬取网页深度，超过深度的页面不再采集
            'max_fields' => 1, //爬虫爬取内容网页最大条数 抓取到一定的字段后退出  默认值为0，即不限制
            'user_agent' => phpspider::AGENT_PC,  //爬虫爬取网页所使用的浏览器类型
            'client_ip' => [                  //爬虫爬取网页所使用的伪IP，用于破解防采集
                '192.168.0.2',
                '192.168.0.3',
                '192.168.0.4',
            ],
            'export' => [         //爬虫爬取数据导出
                'type' => 'db',      //type：导出类型 csv、sql、db
                'table' => 'spider',   // 如果数据表没有数据新增请检查表结构和字段名是否匹配
            ],

            'db_config' => [      //数据库配置
                'host' => '127.0.0.1',
                'port' => '3306',
                'user' => 'root',
                'pass' => 'root',     //密码
                'name' => 'php_spider'  //数据库名
            ],
            'domains' => [        //定义爬虫爬取哪些域名下的网页, 非域名下的url会被忽略以提高爬取速度
                'www.cnbaowen.net',
            ],
            'scan_urls' =>[    //定义爬虫的入口链接, 爬虫从这些链接开始爬取,同时这些链接也是监控爬虫所要监控的链接
                'http://www.cnbaowen.net/news/list-3717.html'         //入口
            ],
            'content_url_regexes' => [   //定义内容页url的规则
                'http://www.cnbaowen.net/news/show-\d+.html'         //文章详情
            ],
            'list_url_regexes' => [   //定义列表页url的规则  对于有列表页的网站, 使用此配置可以大幅提高爬虫的爬取速率
                'http://www.cnbaowen.net/news/list-3717-\d+.html'     //分页
            ],

            'fields' => [       //定义内容页的抽取规则  规则由一个个field组成, 一个field代表一个数据抽取项
                [
                    'name' => "title",   //要跟数据库表中的字段一致
                    'selector' => "//div[@class='exTitle']",  //定义抽取规则, 默认使用xpath
                    'selector_type'=>'xpath',  //目前可用xpath, jsonpath, regex   默认目前可用xpath
                    'required' => true,   // 定义该field的值是否必须, 默认false  赋值为true的话, 如果该field没有抽取到内容, 该field对应的整条数据都将被丢弃
                    'repeated' => false,  //定义该field抽取到的内容是否是有多项, 默认false  赋值为true的话, 无论该field是否真的是有多项, 抽取到的结果都是数组结构
                    'children'=>null,  //为此field定义子项 子项的定义仍然是一个fields数组  没错, 这是一个树形结构
                ],
                [
                    'name' => 'read_num',   //阅读量
                    'selector' => "//div[@class='exTiInfo']",
                    'required' => true,
                ],
                [
                    'name' => 'content',   //文章内容
                    'selector' => "//div[@id='article']",
                    'required' => true,
                ],
                [
                    'name' => 'site_url'
                ],
                [
                    'name' => 'site_id'
                ],
            ],
        );

        $spider = new phpspider($configs);

        $spider->start();;die;

        //开始回调
        $spider->on_start = function ($phpspider) {
            echo "on_start回调开始 ".PHP_EOL;
            for ($i = 1; $i <= 1; $i++) {
                $url = "http://www.cnbaowen.net/news/list-3717-{$i}.html";
                echo "on_start:".$url.PHP_EOL;
                $phpspider->add_url($url);
            }
            echo "on_start回调结束 ".PHP_EOL;
        };

        /**  判断
         * @param $status_code  当前网页的请求返回的HTTP状态码
         * @param $url  当前网页URL
         * @param $content  当前网页内容
         * @param $phpspider  爬虫对象
         * @return bool  $content 返回处理后的网页内容，不处理当前页面请返回false
         */
        $spider->on_status_code = function($status_code, $url, $content, $phpspider)
        {
            // 如果状态码为429，说明对方网站设置了不让同一个客户端同时请求太多次
            if ($status_code == '429')
            {
                // 将url插入待爬的队列中,等待再次爬取
                $phpspider->add_url($url);
                // 当前页先不处理了
                return false;
            }
            // 不拦截的状态码这里记得要返回，否则后面内容就都空了
            return $content;
        };


        /**  判断是否设置了反爬虫
         * @param $url 当前网页的url
         * @param $content 当前网页内容
         * @param $phpspider 爬虫对象
         * @return bool
         */
        $spider->is_anti_spider = function($url, $content, $phpspider)
        {
            // 当前页面没有被反爬虫，可以继续处理
            return false;
        };

        /** 在一个网页下载完成之后调用. 主要用来对下载的网页进行处理.
         * @param $page  当前下载的网页页面的对象
         * @param $page['url'] 当前网页的URL
         * @param $page['raw'] 当前网页的内容
         * @param $page['request'] 当前网页的请求对象
         * @param $phpspider   爬虫对象
         * @return mixed  返回处理后的网页内容
         */
        $spider->on_download_page = function($page, $phpspider)
        {
            return $page;
        };

        /** 在一个网页下载完成之后调用. 主要用来对下载的网页进行处理.
         * @param $content  当前下载的网页内容
         * @param $phpspider  爬虫对象
         * @return mixed  返回处理后的网页内容
         */
        $spider->on_download_attached_page = function($content, $phpspider)
        {
            return $content;
        };

        /** 在一个网页获取到URL之后调用. 主要用来对获取到的URL进行处理.
         * @param $url  当前获取到的URL
         * @param $phpspider  爬虫对象
         * @return bool  返回处理后的URL，为false则此URL不入采集队列
         */
        $spider->on_fetch_url = function($url, $phpspider)
        {
            return $url;
        };

        /**
         * @param $page  当前下载的网页页面的对象
         * @param $page['url'] 当前网页的URL
         * @param $page['raw'] 当前网页的内容
         * @param $page['request'] 当前网页的请求对象
         * @param $content  当前网页内容
         * @param $phpspider  当前爬虫对象
         * @return bool  返回false表示不需要再从此网页中发现待爬url
         */
        $spider->on_scan_page = function($page, $content, $phpspider)
        {
            return false;
        };


        /** 列表回调
         * @param $page
         * @param $content
         * @param $spider
         * @return bool
         */
        $spider->on_list_page = function ($page, $content, $spider) {    //$page = ["url"=>"","raw"=>"","request"=[]]
            echo "on_list_page回调开始 ".PHP_EOL;
//    p("url:".$page['url']);
            p($page);
            $page_type = gettype($page);
            p("page:".$page_type);

            if($page_type == 'array'){
                foreach ($page as $k=>$val){
                    $val_type = gettype($val);
                    p("$k:".$val_type);
                    if($val_type == 'array'){
                        foreach ($page[$k] as $k1=>$val1){
                            $val1_type = gettype($val1);
                            p("$k1:".$val1_type);
                        }
                    }
                }
            }
            $content_type = gettype($content);
            p("content:".$content_type);
            p($content);

            $content = selector::select($content, "//div[@class='news-list-box']");// 右侧详情页
            if (is_array($content)) {
                $content = implode('', $content);
            }
            $regex = "#http://www.cnbaowen.net/news/show-\d+.html#";
            $urls = array();
            preg_match_all($regex, $content, $out);
            $urls = empty($out[0]) ? [] : $out[0];
            $urls = array_unique($urls);

            p($urls);

            if (!empty($urls)) {
                foreach ($urls as $url) {
                    $spider->add_url($url);
                }
            }
            echo "on_list_page回调结束 ".PHP_EOL;
            // 通知爬虫不再从当前网页中发现待爬url
            return false;
        };

        /**
         * @param $page
         * @param $content
         * @param $phpspider
         * @return bool
         */
        $spider->on_content_page = function ($page, $content, $phpspider) {
            echo "on_content_page回调开始 ".PHP_EOL;
            p($page['url']);
            p($content);
            p($page);

            echo "on_content_page回调结束 ".PHP_EOL;
            return false;
        };

        /** 在抽取到field内容之后调用, 对其中包含的img标签进行回调处理
         * @param $fieldname  当前field的name. 注意: 子field的name会带着父field的name, 通过.连接.
         * @param $img  整个img标签的内容
         * @return string|string[]
         */
        $spider->on_handle_img = function($fieldname, $img)
        {
            return $img;
        };

        /**  当一个field的内容被抽取到后进行的回调, 在此回调中可以对网页中抽取的内容作进一步处理
         * @param $fieldname  当前field的name. 注意: 子field的name会带着父field的name, 通过.连接.
         * @param $data  当前field抽取到的数据. 如果该field是repeated, data为数组类型, 否则是String
         * @param $page  当前下载的网页页面的对象
         * @return int|mixed|string
         */
        $spider->on_extract_field = function ($fieldname, $data, $page) {
            echo "on_extract_field回调开始 ".PHP_EOL;
            switch ($fieldname) {
                case 'title':
                    $data = strip_tags($data);
                    return $data;
                case 'read_num':
                    $data = strip_tags($data);
                    return $data;
                case 'content':
                {
                    $s = preg_replace("/<div style=\"float:right[\s\S]*?div>/", "", $data);
                    $s = preg_replace('/<a .*?href="(.*?)".*?>/is', "<a href='#'>", $s);
                    $data = preg_replace('/<img.*?>/is', "", $s);
                    $data = mb_substr($data, 0, 1000);
                    echo "on_extract_field回调结束 ".PHP_EOL;
                    $data = strip_tags($data);
                    return $data;
                }
                case 'site_url':
                    echo "on_extract_field回调结束 ".PHP_EOL;
                    return $page['url'];
                case 'site_id':
                    echo "on_extract_field回调结束 ".PHP_EOL;
                    return 22;
                default:
                    echo "on_extract_field回调结束 ".PHP_EOL;
                    return $data;
            }
        };

        /** 在一个网页的所有field抽取完成之后, 可能需要对field进一步处理, 以发布到自己的网站
         * @param $page  当前下载的网页页面的对象
         * @param $data  当前网页抽取出来的所有field的数据
         * @return mixed  返回处理后的数据, 注意数据类型需要跟传进来的$data类型匹配
         */
        $spider->on_extract_page = function($page, $data)
        {
            return $data;
            // 返回false不处理，当前页面的字段不入数据库直接过滤
            // 比如采集电影网站，标题匹配到“预告片”这三个字就过滤
            //if (strpos($data['title'], "预告片") !== false)
            //{
            //    return false;
            //}
        };

        $spider->start();
    }

}
